﻿using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.List.PlugIn;
using Kingdee.BOS.Orm;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Kingdee.BOS.Core.Bill;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.Metadata.FormElement;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Core;
using Kingdee.BOS.Core.Validation;

namespace RK.ListBillPlugin.XHX
{
    [Description("重新拆分型材领料单，把一部分按比例放到研发；型材恢复"), HotUpdate]
    public class XHX_K3_LinkIt : AbstractListPlugIn
    {
        public override void BarItemClick(BarItemClickEventArgs e)
        {
            base.BarItemClick(e);
            if (e.BarItemKey.EqualsIgnoreCase("tbCreateOutBill"))
            {
                if (this.ListView.SelectedRowsInfo == null || this.ListView.SelectedRowsInfo.Count != 1)
                {
                    this.View.ShowErrMessage("只能选择一个行进行操作!");
                    return;
                }
                var selectId = this.ListView.SelectedRowsInfo.Select(s => (object)s.PrimaryKeyValue).Distinct().ToArray();
                string pkId = selectId[0].ToString();
                //var selectId = this.ListView.SelectedRowsInfo.Select(s => (object)s.PrimaryKeyValue).ToString();
                var selectBillNo = string.Join(",", this.ListView.SelectedRowsInfo.Select(s => (object)s.BillNo).Distinct());
                //var selectBillNo = this.ListView.SelectedRowsInfo.Select(s => (object)s.BillNo);
                string chekBillNo = string.Format(@"SELECT COUNT(T1.FID) FROM T_STK_MISDELIVERY T1 WHERE T1.F_BILLNO1='{0}'", selectBillNo);
                DataSet chekDs = DBServiceHelper.ExecuteDataSet(this.Context, chekBillNo);
                if (int.Parse(chekDs.Tables[0].Rows[0][0].ToString()) > 0)
                {
                    this.View.ShowErrMessage(selectBillNo + "此单已经拆分！，请先确认！", title: "提醒", msgType: MessageBoxType.Error);
                    return;
                }
                string sqlStr = string.Format(@"EXEC CreateOutBill {0}", pkId);
                DataSet dataSet = DBServiceHelper.ExecuteDataSet(this.Context, sqlStr);
                DataTable dt0 = dataSet.Tables[0];
                DataTable dt1 = dataSet.Tables[1];
                if (dt0.Rows.Count > 0)
                {
                    var dataObjects = BusinessDataServiceHelper.Load(this.Context, selectId, this.View.BillBusinessInfo.GetDynamicObjectType());
                    var unAuditResult = BusinessDataServiceHelper.UnAudit(this.Context, this.View.BillBusinessInfo, selectId, OperateOption.Create());
                    if (!unAuditResult.IsSuccess)
                    {
                        this.View.ShowErrMessage("生产领料单：" + selectBillNo + "反审核不成功！，请先确认是否有下游单据。", title: "提醒", msgType: MessageBoxType.Error);
                        return;
                    }
                    #region 拆分前备份数据
                    string reSql = string.Format(@"SELECT T1.FSECACTUALQTY_bk,T1.FACTUALQTY_bk,T1.FBASEACTUALQTY_bk,T1.FSTOCKACTUALQTY_bk,t1.FBASESTOCKACTUALQTY_bk
                        FROM T_PRD_PICKMTRLDATA T1 
                        WHERE T1.FID={0} AND (T1.FSECACTUALQTY_bk>0 OR T1.FACTUALQTY_bk>0 OR T1.FBASEACTUALQTY_bk>0 OR T1.FSTOCKACTUALQTY_bk>0 OR t1.FBASESTOCKACTUALQTY_bk>0)", pkId);
                    DataSet reDataSet = DBServiceHelper.ExecuteDataSet(this.Context, reSql);
                    if (reDataSet.Tables[0].Rows.Count == 0)
                    {
                        string bakSql = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FSECACTUALQTY_bk=T1.FSECACTUALQTY,T1.FACTUALQTY_bk=T1.FACTUALQTY,
                            T1.FBASEACTUALQTY_bk=T1.FBASEACTUALQTY,T1.FSTOCKACTUALQTY_bk=T1.FSTOCKACTUALQTY,
                            t1.FBASESTOCKACTUALQTY_bk=T3.FBASESTOCKACTUALQTY
                            FROM T_PRD_PICKMTRLDATA T1
                            JOIN T_PRD_PICKMTRLDATA_A T3 ON T3.FENTRYID=T1.FENTRYID
                            WHERE T1.FID={0}", pkId);
                        int bakDs = DBServiceHelper.Execute(this.Context, bakSql);
                    }
                    #endregion 拆分前备份数据
                    List<string> sqlArray = new List<string>();
                    for (int i = 0; i < dt0.Rows.Count; i++)
                    {
                        string item = dt0.Rows[i]["FNUMBER"].ToString();
                        int lenght = int.Parse(dt0.Rows[i]["FF100001"].ToString());
                        string color = dt0.Rows[i]["FF100003"].ToString();
                        decimal OutQty = decimal.Parse(dt0.Rows[i]["OutQty"].ToString());
                        decimal FSECACTUALQTY = decimal.Parse(dt0.Rows[i]["FSECACTUALQTY"].ToString());
                        decimal rows = decimal.Parse(dt0.Rows[i]["Rows"].ToString());
                        //decimal average = Math.Round(OutQty / rows, 4, MidpointRounding.AwayFromZero);
                        decimal temOutQty = 0;
                        //decimal lastAge = 0;
                        for (int j = 0; j < dt1.Rows.Count; j++)
                        {
                            string item1 = dt1.Rows[j]["FNUMBER"].ToString();
                            int lenght1 = int.Parse(dt1.Rows[j]["FF100001"].ToString());
                            string color1 = dt1.Rows[j]["FF100003"].ToString();
                            if (item == item1 && lenght1 == lenght && color == color1)
                            {
                                decimal FSECACTUALQTY1 = decimal.Parse(dt1.Rows[j]["FSECACTUALQTY"].ToString());
                                decimal average = Math.Round(FSECACTUALQTY1 / FSECACTUALQTY * OutQty, 4, MidpointRounding.AwayFromZero);
                                decimal newQty = FSECACTUALQTY1 - average;
                                int FENTRYID = int.Parse(dt1.Rows[j]["FENTRYID"].ToString());

                                if (rows > 1)
                                {
                                    string otherOutQtyStr = string.Format(@"/*dialect*/ UPDATE T1 SET T1.F_OtherOutQty={0} FROM T_PRD_PICKMTRLDATA T1 WHERE T1.FENTRYID={1}", average, FENTRYID);
                                    sqlArray.Add(otherOutQtyStr);
                                    string FSECACTUALQTY1Str = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FSECACTUALQTY={0} FROM T_PRD_PICKMTRLDATA T1 WHERE T1.FENTRYID={1}", newQty, FENTRYID);
                                    sqlArray.Add(FSECACTUALQTY1Str);
                                    string FACTUALQTYstr = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FACTUALQTY={0} FROM T_PRD_PICKMTRLDATA T1 WHERE T1.FENTRYID={1}", lenght1 * newQty, FENTRYID);
                                    sqlArray.Add(FACTUALQTYstr);
                                    string FBASEACTUALQTYStr = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FBASEACTUALQTY={0} FROM T_PRD_PICKMTRLDATA T1 WHERE T1.FENTRYID={1}", lenght1 * newQty / 1000, FENTRYID);
                                    sqlArray.Add(FBASEACTUALQTYStr);
                                    string FSTOCKACTUALQTYStr = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FSTOCKACTUALQTY={0} FROM T_PRD_PICKMTRLDATA T1 WHERE T1.FENTRYID={1}", lenght1 * newQty / 1000, FENTRYID);
                                    sqlArray.Add(FSTOCKACTUALQTYStr);
                                    string FBASESTOCKACTUALQTYStr = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FBASESTOCKACTUALQTY={0} FROM T_PRD_PICKMTRLDATA_A T1 WHERE T1.FENTRYID={1}", lenght1 * newQty / 1000, FENTRYID);
                                    sqlArray.Add(FBASESTOCKACTUALQTYStr);
                                    temOutQty = temOutQty + average;
                                    //lastAge = OutQty - temOutQty; 
                                }
                                if (rows == 1)
                                {
                                    string otherOutQtyStr = string.Format(@"/*dialect*/ UPDATE T1 SET T1.F_OtherOutQty={0} FROM T_PRD_PICKMTRLDATA T1 WHERE T1.FENTRYID={1}", OutQty - temOutQty, FENTRYID);
                                    sqlArray.Add(otherOutQtyStr);
                                    string FSECACTUALQTY1Str = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FSECACTUALQTY={0} FROM T_PRD_PICKMTRLDATA T1 WHERE T1.FENTRYID={1}", FSECACTUALQTY1 - (OutQty - temOutQty), FENTRYID);
                                    sqlArray.Add(FSECACTUALQTY1Str);
                                    string FACTUALQTYstr = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FACTUALQTY={0} FROM T_PRD_PICKMTRLDATA T1 WHERE T1.FENTRYID={1}", lenght1 * (FSECACTUALQTY1 - (OutQty - temOutQty)), FENTRYID);
                                    sqlArray.Add(FACTUALQTYstr);
                                    string FBASEACTUALQTYStr = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FBASEACTUALQTY={0} FROM T_PRD_PICKMTRLDATA T1 WHERE T1.FENTRYID={1}", lenght1 * (FSECACTUALQTY1 - (OutQty - temOutQty)) / 1000, FENTRYID);
                                    sqlArray.Add(FBASEACTUALQTYStr);
                                    string FSTOCKACTUALQTYStr = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FSTOCKACTUALQTY={0} FROM T_PRD_PICKMTRLDATA T1 WHERE T1.FENTRYID={1}", lenght1 * (FSECACTUALQTY1 - (OutQty - temOutQty)) / 1000, FENTRYID);
                                    sqlArray.Add(FSTOCKACTUALQTYStr);
                                    string FBASESTOCKACTUALQTYStr = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FBASESTOCKACTUALQTY={0} FROM T_PRD_PICKMTRLDATA_A T1 WHERE T1.FENTRYID={1}", lenght1 * (FSECACTUALQTY1 - (OutQty - temOutQty)) / 1000, FENTRYID);
                                    sqlArray.Add(FBASESTOCKACTUALQTYStr);
                                }
                                else
                                {

                                }
                                rows--;
                            }
                        }
                    }
                    if (sqlArray.Count > 0)
                    {
                        int res = 0;
                        using (KDTransactionScope scope = new KDTransactionScope(TransactionScopeOption.Required))
                        {
                            res = DBServiceHelper.ExecuteBatch(this.Context, sqlArray);
                            scope.Complete();
                        }
                        if (res <= 0)
                        {
                            this.View.ShowErrMessage("数据操作失败！");
                            return;
                        }
                    }
                    var result = BusinessDataServiceHelper.Save(this.Context, this.View.BillBusinessInfo, dataObjects);
                    if (result.IsSuccess)
                    {
                        //this.View.ShowMessage(string.Format("单据【{0}】保存成功！", selectBillNo));
                        var sumbitResult = BusinessDataServiceHelper.Submit(this.Context, this.View.BillBusinessInfo, selectId, "Submit", OperateOption.Create());
                        if (sumbitResult.IsSuccess)
                        {
                            var AuditResult = BusinessDataServiceHelper.Audit(this.Context, this.View.BillBusinessInfo, selectId, OperateOption.Create());
                            if (AuditResult.IsSuccess)
                            {
                                //审核成功才生成其他出库单
                                string otherOutBillStr = string.Format(@"EXEC CreateOtherOutBill {0}", pkId);
                                DataSet otherOutBillStrDs = DBServiceHelper.ExecuteDataSet(this.Context, otherOutBillStr);
                                autoCreateOutBill(otherOutBillStrDs.Tables[0]);
                            }
                        }
                    }
                    else
                    {
                        FormatOperateResultValidationInfo(result);
                        this.View.ShowOperateResult(result.OperateResult);
                    }
                }
                else
                {
                    this.View.ShowErrMessage(selectBillNo + "没有可拆分的数据，请确认！", title: "拆分控制", msgType: MessageBoxType.Error);
                    return;
                }
            }
            //型材恢复
            if (e.BarItemKey.EqualsIgnoreCase("TRPU_tbButton_recover"))
            {
                if (this.ListView.SelectedRowsInfo == null || this.ListView.SelectedRowsInfo.Count != 1)
                {
                    this.View.ShowErrMessage("只能选择一个行进行恢复!");
                    return;
                }
                var selectId = this.ListView.SelectedRowsInfo.Select(s => (object)s.PrimaryKeyValue).Distinct().ToArray();
                string pkId = selectId[0].ToString();
                var dataObjects = BusinessDataServiceHelper.Load(this.Context, selectId, this.View.BillBusinessInfo.GetDynamicObjectType());
                var unAuditResult = BusinessDataServiceHelper.UnAudit(this.Context, this.View.BillBusinessInfo, selectId, OperateOption.Create());
                if (!unAuditResult.IsSuccess)
                {
                    this.View.ShowErrMessage("反审核不成功！，请先确认是否有下游单据。", title: "提醒", msgType: MessageBoxType.Error);
                    return;
                }
                string reSql = string.Format(@"SELECT T1.FSECACTUALQTY_bk,T1.FACTUALQTY_bk,T1.FBASEACTUALQTY_bk,T1.FSTOCKACTUALQTY_bk,t1.FBASESTOCKACTUALQTY_bk
                    FROM T_PRD_PICKMTRLDATA T1 
                    WHERE T1.FID={0} AND (T1.FSECACTUALQTY_bk=0 OR T1.FACTUALQTY_bk=0 OR T1.FBASEACTUALQTY_bk=0 OR T1.FSTOCKACTUALQTY_bk=0 OR t1.FBASESTOCKACTUALQTY_bk=0)", pkId);
                DataSet reDs = DBServiceHelper.ExecuteDataSet(this.Context, reSql);
                if (reDs.Tables[0].Rows.Count > 0)
                {
                    this.View.ShowErrMessage("未拆分过，不允许恢复！", title: "提醒", msgType: MessageBoxType.Error);
                    return;
                }
                List<string> sqlArray = new List<string>();
                int upRes = 0;
                string upSql1 = string.Format(@"/*dialect*/ UPDATE T1 SET T1.FSECACTUALQTY=T1.FSECACTUALQTY_bk,T1.FACTUALQTY=T1.FACTUALQTY_bk,T1.FBASEACTUALQTY=T1.FBASEACTUALQTY_bk,T1.FSTOCKACTUALQTY=T1.FSTOCKACTUALQTY_bk,T1.F_OtherOutQty=0 
                    FROM T_PRD_PICKMTRLDATA T1
                    WHERE T1.FID={0}", pkId);
                sqlArray.Add(upSql1);
                string upSql2 = string.Format(@"/*dialect*/ UPDATE T2 SET T2.FBASESTOCKACTUALQTY=t1.FBASESTOCKACTUALQTY_bk
                    FROM T_PRD_PICKMTRLDATA T1
                    JOIN T_PRD_PICKMTRLDATA_A T2 ON T2.FENTRYID=T1.FENTRYID
                    WHERE T1.FID={0}", pkId);
                sqlArray.Add(upSql2);
                if (sqlArray.Count > 0)
                {
                    upRes = DBServiceHelper.ExecuteBatch(this.Context, sqlArray);
                }
                if (upRes > 0)
                {
                    var result = BusinessDataServiceHelper.Save(this.Context, this.View.BillBusinessInfo, dataObjects);
                    if (result.IsSuccess)
                    {
                        //this.View.ShowMessage(string.Format("单据【{0}】保存成功！", selectBillNo));
                        var sumbitResult = BusinessDataServiceHelper.Submit(this.Context, this.View.BillBusinessInfo, selectId, "Submit", OperateOption.Create());
                        if (sumbitResult.IsSuccess)
                        {
                            var AuditResult = BusinessDataServiceHelper.Audit(this.Context, this.View.BillBusinessInfo, selectId, OperateOption.Create());
                            if (AuditResult.IsSuccess)
                            {
                                this.View.ShowMessage("型材恢复成功！", msgType: MessageBoxType.Notice);
                            }
                        }
                    }
                    else
                    {
                        FormatOperateResultValidationInfo(result);
                        this.View.ShowOperateResult(result.OperateResult);
                    }
                }
                else
                {
                    this.View.ShowErrMessage("型材恢复失败！", title: "提醒", msgType: MessageBoxType.Error);
                    return;
                }
            }

        }
        /// <summary>
        /// 将操作返回结果中的校验信息合并到操作结果集中
        /// </summary>
        /// <param name="result"></param>
        protected virtual void FormatOperateResultValidationInfo(IOperationResult result)
        {
            if (result.ValidationErrors == null || result.ValidationErrors.Count == 0)
            {
                return;
            }
            var collection = result.OperateResult;
            foreach (var errorInfo in result.ValidationErrors)
            {
                var rs = new OperateResult
                {
                    PKValue = errorInfo.BillPKID,
                    RowIndex = errorInfo.RowIndex,
                    Name = errorInfo.Title,
                    SuccessStatus = false,
                    Message = errorInfo.Message,
                    MessageType = errorInfo.Level == ErrorLevel.Warning ? MessageType.Warning : MessageType.FatalError
                };
                collection.Add(rs);
            }
        }

        /// <summary>
        /// 自动创建其他出库单
        /// </summary>
        /// <param name="piMtlBillNo"></param>
        /// <param name="dt"></param>
        private void autoCreateOutBill(DataTable dt)
        {
            IBillView billView = this.CreateView();
            ((IBillViewService)billView).LoadData();
            DynamicFormViewPlugInProxy eventProxy = billView.GetService<DynamicFormViewPlugInProxy>();
            eventProxy.FireOnLoad();
            this.fillData(billView, dt);
            OperateOption saveOption = OperateOption.Create();
            this.SaveBill(billView, saveOption);
        }

        private void SaveBill(IBillView billView, OperateOption saveOption)
        {
            throw new NotImplementedException();
        }

        private void fillData(IBillView billView, DataTable dt)
        {
            IDynamicFormViewService dynamicFormView = billView as IDynamicFormViewService;
            //单据头
            billView.Model.SetItemValueByNumber("FBillTypeID", "QTCKD01_SYS", 0);//单据类型
            //billView.Model.SetValue("BizType", 0, 0);//业务类型
            billView.Model.SetValue("FDate", dt.Rows[0]["FDATE"].ToString(), 0);//日期
            billView.Model.SetValue("F_BillNO1", dt.Rows[0]["FBILLNO"].ToString(), 0);//手工领料单号
            billView.Model.SetItemValueByNumber("FStockOrgId", "003", 0);//库存组织
            billView.Model.SetItemValueByNumber("FPickOrgId", "100", 0);//领用组织
            //billView.Model.SetItemValueByNumber("OwnerTypeIdHead", "BD_OwnerOrg", 0);//货主类型
            billView.Model.SetItemValueByNumber("FOwnerIdHead", "003", 0);//货主
            billView.Model.SetItemValueByNumber("FDeptId", "0060", 0);//领料部门
            billView.Model.SetItemValueByNumber("FCreatorId", "Administrator", 0);//创建人

            billView.Model.ClearNoDataRow();

            //写入明细表
            billView.Model.BatchCreateNewEntryRow("FEntity", dt.Rows.Count);
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                dynamicFormView.SetItemValueByNumber("FMaterialId", dt.Rows[i]["FNUMBER"].ToString(), i);
                dynamicFormView.UpdateValue("FAuxPropId", i, int.Parse(dt.Rows[i]["FAUXPROPID"].ToString()));
                dynamicFormView.UpdateValue("$$FAUXPROPID__FF100001", i, dt.Rows[i]["FF100001"].ToString());//辅助属性长
                dynamicFormView.UpdateValue("$$FAUXPROPID__FF100003", i, dt.Rows[i]["FF100003"].ToString());//辅助属性颜色
                dynamicFormView.SetItemValueByID("FStockId", int.Parse(dt.Rows[i]["FSTOCKID"].ToString()), i);
                dynamicFormView.UpdateValue("FExtAuxUnitQty", i, double.Parse(dt.Rows[i]["OutQty"].ToString()));//实发数量（辅单位）
                dynamicFormView.UpdateValue("FQty", i, double.Parse(dt.Rows[i]["OutQty"].ToString()) * double.Parse(dt.Rows[i]["FF100001"].ToString()) / 100);//实发数量（辅单位）
                dynamicFormView.SetItemValueByNumber("F_TRPU_Assistant", "007", i);
                billView.InvokeFieldUpdateService("FExtAuxUnitQty", i);
            }
            billView.Model.ClearNoDataRow();
        }

        private IBillView CreateView()
        {
            FormMetadata meta = MetaDataServiceHelper.Load(this.Context, "STK_MisDelivery") as FormMetadata;
            Form form = meta.BusinessInfo.GetForm();
            Type type = Type.GetType("Kingdee.BOS.Web.Import.ImportBillView,Kingdee.BOS.Web");
            var billView = (IDynamicFormViewService)Activator.CreateInstance(type);
            BillOpenParameter openParam = CreateOpenParameter(meta);
            var provider = form.GetFormServiceProvider();
            billView.Initialize(openParam, provider);
            return billView as IBillView;
        }

        private BillOpenParameter CreateOpenParameter(FormMetadata meta)
        {
            Form form = meta.BusinessInfo.GetForm();
            BillOpenParameter openParam = new BillOpenParameter(form.Id, meta.GetLayoutInfo().Id);
            openParam.Context = this.Context;
            openParam.ServiceName = form.FormServiceName;
            openParam.PageId = Guid.NewGuid().ToString();
            openParam.FormMetaData = meta;
            openParam.Status = OperationStatus.ADDNEW;
            openParam.PkValue = null;
            openParam.CreateFrom = CreateFrom.Default;
            openParam.GroupId = "";
            openParam.ParentId = 0;
            openParam.DefaultBillTypeId = "";
            openParam.DefaultBusinessFlowId = "";
            openParam.SetCustomParameter("ShowConfirmDialogWhenChangeOrg", false);
            List<AbstractDynamicFormPlugIn> plugs = form.CreateFormPlugIns();
            openParam.SetCustomParameter(FormConst.PlugIns, plugs);
            PreOpenFormEventArgs args = new PreOpenFormEventArgs(this.Context, openParam);
            foreach (var plug in plugs)
            {
                plug.PreOpenForm(args);
            }
            if (args.Cancel == true)
            {
                // 不理会插件的诉求，继续....
            }
            return openParam;
        }
    }
}
